<template>
  <div class="file_select" @click="handleBeforeUpload">
    <slot></slot>
    <input
      ref="file"
      type="file"
      accept="image/png, image/jpeg, image/gif, image/jpg"
      @change="handleChange"
      style="display: none"
    />
    <el-dialog title="更换头像" v-model="isShowDialog" width="769px">
      <div class="cropper-warp">
        <div class="cropper-warp-left">
          <img :src="cropperImg" class="cropper-warp-left-img" />
        </div>
        <div class="cropper-warp-right">
          <div class="cropper-warp-right-title">预览</div>
          <div class="cropper-warp-right-item">
            <div class="cropper-warp-right-value">
              <img :src="cropperImgBase64" class="cropper-warp-right-value-img" />
            </div>
            <div class="cropper-warp-right-label">100 x 100</div>
          </div>
          <div class="cropper-warp-right-item">
            <div class="cropper-warp-right-value">
              <img :src="cropperImgBase64" class="cropper-warp-right-value-img cropper-size" />
            </div>
            <div class="cropper-warp-right-label">50 x 50</div>
          </div>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="onCancel" size="small">取 消</el-button>
          <el-button :loading="submitLoading" type="primary" @click="onSubmit" size="small"
            >上 传</el-button
          >
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts">
import { reactive, toRefs, nextTick, ref, unref } from 'vue'
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'
import { ElNotification } from 'element-plus'
import axios from 'axios'
import { getQiniuToken } from '@/api/common/index'
import { PropType } from '@/global'
export default {
  name: 'cropperIndex',
  props: {
    category: {
      type: String as PropType<string>,
      default: 'inst_student_avatar'
    }
  },
  emits: ['success'],
  setup(props, { emit }) {
    const file = ref<HTMLElement | null>(null)
    let cropper: any = null
    const state = reactive({
      isShowDialog: false,
      cropperImg: '',
      cropperImgBase64: '',
      submitLoading: false,
      uploadFile: null
    })
    // 选择图片
    const handleBeforeUpload = () => {
      ;(unref(file) as any).click()
    }
    // 选择图片
    const handleChange = (e: any) => {
      const file = e.target.files[0]
      if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {
        ElNotification({
          title: '提示',
          message: '图片类型必须是.jpeg,jpg,png中的一种',
          type: 'warning'
        })
        unref(file).value = ''
        return false
      }
      state.uploadFile = file
      const reader = new FileReader()
      reader.onload = (res: any) => {
        let data
        if (typeof res.target.result === 'object') {
          // 把Array Buffer转化为blob 如果是base64不需要
          data = window.URL.createObjectURL(new Blob([e.target.result]))
        } else {
          data = res.target.result
        }
        openDialog(data)
      }
      // 转化为base64
      reader.readAsDataURL(file)
      // 转化为blob
      // reader.readAsArrayBuffer(file)
    }
    // 打开弹窗
    const openDialog = (imgs: any) => {
      state.cropperImg = imgs
      state.isShowDialog = true
      nextTick(() => {
        initCropper()
      })
    }
    // 关闭弹窗
    const closeDialog = () => {
      state.isShowDialog = false
    }
    // 取消
    const onCancel = () => {
      closeDialog()
    }
    // 提交上传
    const onSubmit = () => {
      if (!cropper) return
      cropper.getCroppedCanvas().toBlob((blob: Blob) => {
        uploadFile(blob)
      })
    }
    // 图片上传
    const uploadFile = async (blob: Blob) => {
      state.submitLoading = true
      try {
        const { code, data, message } = await getQiniuToken({
          fullName: (state.uploadFile as any).name,
          category: props.category
        })
        if (code === 200) {
          const formData = new FormData()
          formData.append('file', blob, (state.uploadFile as any).name.replace(/\s+/g, ''))
          formData.append('token', data.token)
          formData.append('key', data.fileKey)
          const result: any = await axios.post(data.domain, formData, {
            headers: { 'Content-Type': 'multipart/form-data' }
          })
          if (result.data.code === 200) {
            emit('success', result.data.data)
            state.submitLoading = false
            onCancel()
          } else {
            state.submitLoading = false
            ElNotification({
              title: '错误',
              message: '上传失败',
              type: 'error'
            })
          }
        } else {
          state.submitLoading = false
          ElNotification({
            title: '错误',
            message: message,
            type: 'error'
          })
        }
      } catch (error) {
        console.error(error)
      }
    }
    // 初始化cropperjs图片裁剪
    const initCropper = () => {
      const letImg: any = document.querySelector('.cropper-warp-left-img')
      cropper = new Cropper(letImg, {
        viewMode: 1,
        dragMode: 'none',
        initialAspectRatio: 1,
        aspectRatio: 1,
        preview: '.before',
        background: false,
        autoCropArea: 0.6,
        zoomOnWheel: false,
        crop: () => {
          state.cropperImgBase64 = cropper.getCroppedCanvas().toDataURL('image/jpeg')
        }
      })
    }
    return {
      file,
      handleBeforeUpload,
      handleChange,
      openDialog,
      closeDialog,
      onCancel,
      onSubmit,
      initCropper,
      ...toRefs(state)
    }
  }
}
</script>

<style scoped lang="scss">
.cropper-warp {
  display: flex;
  .cropper-warp-left {
    position: relative;
    display: inline-block;
    height: 350px;
    flex: 1;
    border: 1px solid #ebeef5;
    background: #fff;
    overflow: hidden;
    background-repeat: no-repeat;
    cursor: move;
    border-radius: 3px;
    .cropper-warp-left-img {
      width: 100%;
      height: 100%;
    }
  }
  .cropper-warp-right {
    width: 150px;
    height: 350px;
    .cropper-warp-right-title {
      text-align: center;
      height: 20px;
      line-height: 20px;
    }
    .cropper-warp-right-item {
      margin: 15px 0;
      .cropper-warp-right-value {
        display: flex;
        .cropper-warp-right-value-img {
          width: 100px;
          height: 100px;
          border-radius: 100%;
          margin: auto;
        }
        .cropper-size {
          width: 50px;
          height: 50px;
        }
      }
      .cropper-warp-right-label {
        text-align: center;
        font-size: 12px;
        color: #666666;
        height: 30px;
        line-height: 30px;
      }
    }
  }
}
</style>
